package ru.ifmo.swing.genetics.config.operator;

import org.uncommons.maths.number.NumberGenerator;
import org.uncommons.maths.random.Probability;
import org.uncommons.watchmaker.framework.EvaluatedCandidate;
import org.uncommons.watchmaker.swing.NumericParameterControl;
import org.uncommons.watchmaker.swing.ProbabilityParameterControl;
import ru.ifmo.automaton.Automaton;
import ru.ifmo.common.Source;
import ru.ifmo.genetics.adaptation.AdaptableParameter;
import ru.ifmo.genetics.adaptation.CorrectingProbabilityGenerator;
import ru.ifmo.swing.EvolutionControlWithConfigProvider;
import ru.ifmo.swing.Panel;

import javax.swing.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author avhaliullin
 */
public class CorrectingProbabilityControl implements NumberGenerator<Probability>, EvolutionControlWithConfigProvider, AdaptableParameter<String> {
    private final CorrectingProbabilityGenerator generator;
    private final ProbabilityParameterControl probabilityControl;
    private final NumericParameterControl<Double> increaseControl;
    private Panel control;

    public CorrectingProbabilityControl(Source<Automaton<Character, String>> automatonSource, double defaultInitialProbability,
                                        double defaultIncrease) {
        probabilityControl = new ProbabilityParameterControl(new Probability(defaultInitialProbability));
        increaseControl = new NumericParameterControl<Double>(0d, 1d, 0.01, defaultIncrease);

        control = new Panel();
        control.setHorizontal(false);

        Panel probability = new Panel();
        probability.setHorizontal(true);
        probability.add(new JLabel("Initial probability: "));
        probability.add(probabilityControl.getControl());
        control.add(probability);

        Panel increase = new Panel();
        increase.setHorizontal(true);
        increase.add(new JLabel("Increase: "));
        increase.add(increaseControl.getControl());
        control.add(increase);
        generator = new CorrectingProbabilityGenerator(probabilityControl.getNumberGenerator(),
                automatonSource, increaseControl.getNumberGenerator());
    }

    public Probability nextValue() {
        return generator.nextValue();
    }

    public JComponent getControl() {
        return control;
    }

    public void reset() {
    }

    public void setDescription(String description) {
        control.setTitle(description);
    }

    public void adapt(List<List<EvaluatedCandidate<String>>> lastGenerations) {
        generator.adapt(lastGenerations);
    }

    public Map<String, Object> getParamValues() {
        Map<String, Object> res = new HashMap<String, Object>();
        res.put("Initial prob.", probabilityControl.getNumberGenerator().nextValue());
        res.put("Increase", increaseControl.getNumberGenerator().nextValue());
        return res;
    }
}
